package cn.jimmie.learn.viewArt.weight

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.os.Build
import android.support.annotation.RequiresApi
import android.util.AttributeSet
import android.view.animation.LinearInterpolator
import java.util.*

/**
 * function :
 *
 * <p> Create Time:  2019年01月08日 19:57 </p>
 * <p> @author Jimmie.Qian  </p>
 */

class TmpView(context: Context, attrs: AttributeSet) : BaseView(context, attrs) {
    private val mPath = Path()
    private val mCamera = Camera()
    private val mMatrix = Matrix()
    private var mActionDegree = 0f
    private var mMoveDegree = 0f
    private var orientation = TOP
    private var mOrientationAnimator = ValueAnimator.ofFloat()
    private var mDistance = 0f

    private var isWay = true
    private var record = 0

    private var mX: Float
    private var mY: Float

    private val UNIT = 3_000f / h
    private val SPEED = 4f

    private val mRandom = Random()

    fun go(o: Int) {
        orientation = o

        val duration = when (o) {
            LEFT -> {
                mMoveDegree = 270f
                mDistance = mX
                mDistance * UNIT
            }
            RIGHT -> {
                mMoveDegree = 90f
                mDistance = w - mX
                mDistance * UNIT
            }
            TOP -> {
                mMoveDegree = 0f
                mDistance = mY
                mDistance * UNIT
            }
            else -> {
                mMoveDegree = 180f
                mDistance = h - mY
                mDistance * UNIT
            }
        }
        mOrientationAnimator.setFloatValues(mDistance)
        mOrientationAnimator.duration = duration.toLong()
        mOrientationAnimator.start()
    }

    init {
        paint.strokeWidth = 10 * dp
        paint.color = Color.GREEN

        mX = w / 2f
        mY = h / 2f

        val animator = ValueAnimator.ofInt(150_000)
        animator.interpolator = LinearInterpolator()
        animator.duration = (15000_000 / SPEED).toLong()
        animator.start()

        animator.addUpdateListener {
            val value = it.animatedValue as Int % 15
            if (value < record) isWay = !isWay
            record = value

            mActionDegree = if (isWay) 35 + value * 1f else 50 - value * 1f
            invalidate()
        }

        mOrientationAnimator.interpolator = LinearInterpolator()
        mOrientationAnimator.addUpdateListener {
            val value = it.animatedValue as Float

            when (orientation) {
                LEFT -> {
                    mX = mDistance - value
                }
                RIGHT -> {
                    mX = w - mDistance + value
                }
                TOP -> {
                    mY = mDistance - value
                }
                BOTTOM -> {
                    mY = h - mDistance + value
                }
            }
            invalidate()
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onDraw(canvas: Canvas) {
        if (checkHit()) {
            createFoodXY()
        }
        paint.color = Color.YELLOW
        canvas.drawPoint(mFoodX, mFoodY, paint)
        canvas.save()
        canvas.translate(mX - w / 2, mY - h / 2)
        canvas.rotate(mMoveDegree, w / 2f, h / 2f)
        canvas.scale(0.2f, 0.2f, w / 2f, h / 2f)
        drawButterfly(canvas)
        canvas.restore()
    }

    private var mFoodX = 0f
    private var mFoodY = 0f
    private fun createFoodXY() {
        mFoodX = mRandom.nextInt(w).toFloat()
        mFoodY = mRandom.nextInt(h).toFloat()
    }

    private fun checkHit(): Boolean {
        if (mFoodX == 0f && mFoodY == 0f) {
            return true
        }
        return (Math.abs(mFoodX - mX) < 0.06f * w && Math.abs(mFoodY - mY) < 0.06f * h)
    }

    private fun drawButterflyLeft(canvas: Canvas) {
        mPath.reset()
        mPath.moveTo(w / 2f, h / 2f)
        mPath.cubicTo(
            w / 5f, -0.5f * h,
            0f, 0.65f * h,
            w / 2f, h / 2f
        )
        mPath.cubicTo(
            w / 5f, 0.4f * h,
            w / 5f, 1.2f * h,
            w / 2f, h / 2f
        )
        paint.color = Color.GREEN
        canvas.drawPath(mPath, paint)
        paint.color = Color.RED
        canvas.drawCircle(0.3f * w, 0.28f * h, w / 20f, paint)
    }

    private fun drawButterflyRight(canvas: Canvas) {
        mPath.reset()
        mPath.moveTo(w / 2f, h / 2f)
        mPath.cubicTo(
            w * 4f / 5, -0.5f * h,
            w * 1f, 0.65f * h,
            w / 2f, h / 2f
        )
        mPath.cubicTo(
            w * 4f / 5, 0.4f * h,
            w * 4f / 5, 1.2f * h,
            w / 2f, h / 2f
        )
        paint.color = Color.GREEN
        canvas.drawPath(mPath, paint)
        paint.color = Color.RED
        canvas.drawCircle(0.7f * w, 0.28f * h, w / 20f, paint)
    }

    private fun cameraRotate(canvas: Canvas, degree: Float) {
        mCamera.save()
        if (mActionDegree > 0) mCamera.setLocation(0f, 0f, 8f)
        mCamera.rotate(0f, degree, 0f)
        mCamera.getMatrix(mMatrix)
        mMatrix.preTranslate(-w / 2f, -h / 2f)
        mMatrix.postTranslate(w / 2f, h / 2f)
        canvas.concat(mMatrix)
        mCamera.restore()
    }


    private fun drawButterfly(canvas: Canvas) {
        canvas.save()
        canvas.clipRect(0, 0, w / 2, h)
        cameraRotate(canvas, Math.abs(mActionDegree))
        drawButterflyLeft(canvas)
        canvas.restore()

        canvas.clipRect(w / 2, 0, w, h)
        cameraRotate(canvas, -Math.abs(mActionDegree))
        drawButterflyRight(canvas)
    }

    companion object {
        const val LEFT = 1
        const val RIGHT = 2
        const val TOP = 3
        const val BOTTOM = 4
    }
}